package services

import (
	"context"
	"errors"
	"fmt"
	"strings"

	"github.com/google/uuid"
	"github.com/sysadminsmedia/homebox/backend/internal/data/repo"
)

var (
	ErrNotFound     = errors.New("not found")
	ErrFileNotFound = errors.New("file not found")
)

type ItemService struct {
	repo *repo.AllRepos

	filepath string

	autoIncrementAssetID bool
}

func (svc *ItemService) Create(ctx Context, item repo.ItemCreate) (repo.ItemOut, error) {
	if svc.autoIncrementAssetID {
		highest, err := svc.repo.Items.GetHighestAssetID(ctx, ctx.GID)
		if err != nil {
			return repo.ItemOut{}, err
		}

		item.AssetID = highest + 1
	}

	return svc.repo.Items.Create(ctx, ctx.GID, item)
}

func (svc *ItemService) EnsureAssetID(ctx context.Context, gid uuid.UUID) (int, error) {
	items, err := svc.repo.Items.GetAllZeroAssetID(ctx, gid)
	if err != nil {
		return 0, err
	}

	highest, err := svc.repo.Items.GetHighestAssetID(ctx, gid)
	if err != nil {
		return 0, err
	}

	finished := 0
	for _, item := range items {
		highest++

		err = svc.repo.Items.SetAssetID(ctx, gid, item.ID, highest)
		if err != nil {
			return 0, err
		}

		finished++
	}

	return finished, nil
}

func (svc *ItemService) EnsureImportRef(ctx context.Context, gid uuid.UUID) (int, error) {
	ids, err := svc.repo.Items.GetAllZeroImportRef(ctx, gid)
	if err != nil {
		return 0, err
	}

	finished := 0
	for _, itemID := range ids {
		ref := uuid.New().String()[0:8]

		err = svc.repo.Items.Patch(ctx, gid, itemID, repo.ItemPatch{ImportRef: &ref})
		if err != nil {
			return 0, err
		}

		finished++
	}

	return finished, nil
}

func serializeLocation[T ~[]string](location T) string {
	return strings.Join(location, "/")
}


// ClearInventory deletes all items in the specified group
func (svc *ItemService) ClearInventory(ctx context.Context, gid uuid.UUID) (int, error) {
	// Get all items to count how many will be deleted
	items, err := svc.repo.Items.GetAll(ctx, gid)
	if err != nil {
		return 0, err
	}

	count := len(items)
	if count == 0 {
		return 0, nil
	}

	// Delete all items one by one to ensure proper cleanup
	// This also handles related attachments and fields through cascade deletes
	for _, item := range items {
		err := svc.repo.Items.DeleteByGroup(ctx, gid, item.ID)
		if err != nil {
			return 0, fmt.Errorf("failed to delete item %s: %w", item.ID, err)
		}
	}

	return count, nil
}
